<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Ruby/Tk Tutorial: Ruby Study Notes - Best Ruby Guide, Ruby Tutorial</title>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<meta name="description" content="Ruby Study Notes - Best Ruby Guide, Ruby Tutorial" />
<meta name="keywords" content="ruby study notes,ruby/tk,Ruby/Tk,ruby tk tutorial,ruby/tk tutorial,tk ruby tutorial,rubytk tutorial,ruby tutorials,ruby tutorial,learn ruby,ruby,ruby on rails,ruby rails,ruby learning,ruby tutoring,learning ruby,ruby programming,ruby on rails development,ruby training" />
<meta name="Distribution" content="Global" />
<meta name="author" content="Satish Talim / Original design: Erwin Aligam - ealigam@gmail.com" />
<meta name="copyright" content="Satish Talim 2007 and beyond..." />
<meta name="verify-v1" content="rFu86se+IkbtF+bH8mgJBKwU5HnKaSd8Ghw9umXQOkM=" />
<meta name="robots" content="index,follow" />
<meta http-equiv="Expires" content="0" />
<meta name="revisit-after" content="1 days" />
<link rel="stylesheet" href="/images/NewOrange.css" type="text/css" />
<link rel="stylesheet" href="/images/syntaxhighlighter.css" type="text/css" />
<!-- Google Analytics code -->
<script type="text/javascript">

  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-59044-10']);
  _gaq.push(['_trackPageview']);

  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();

</script>
<!-- Google Analytics code ends -->
</head>

<body>
<!-- wrap starts here -->
<div id="wrap">

    <div id="header">

        <h1 id="logo">Ruby<span class="orange">Learning.github.io</span></h1>
        <h2 id="slogan">Ruby helps programmers have more fun!</h2>

    </div>

    <div id="menu">
        <ul>
            <li><a href="/" title="Home page for rubylearning.github.io">Home</a></li>
            <li id="current"><a href="/satishtalim/tutorial.html" title="Get started Learning Ruby here...">Tutorial</a></li>
            <li><a href="/download/downloads.html" title="Download this tutorial as an eBook">Downloads</a></li>
            <li><a href="/other/testimonials.html" title="People around the world who benefited from this site">Testimonials</a></li>
            <li><a href="/other/ruby_gurus.html" title="Interviews I took of Ruby Gurus around the world">Gurus</a></li>
            <li><a href="/other/certification.html" title="Get certified in Ruby">Certification</a></li>
            <li><a href="/satishtalim/ruby_guide.html" title="Ruby Guide, Mentor">Mentor</a></li>
            <li><a href="/other/ruby_video_search.html" title="Watch videos on Ruby/Rails">Videos</a></li>
            <li><a href="/blog/" title="Ruby blog of Learning Ruby site">Blog</a></li>
            <li><a href="/satishtalim/tutorial.html" title="Online Ruby Course">Online Course</a></li>
            <li><a href="/contact/contact.html" title="Contacting Satish Talim">Contact</a></li>
            <li><a href="/satishtalim/about.html" title="Information about Satish Talim">About</a></li>
        </ul>
    </div>

    <!-- content-wrap starts here -->
    <div id="content-wrap">

            <div id="main">

                <div id="main-inner"><a name="TemplateInfo"></a>
                <h1>Ruby/Tk Tutorial</h1>


                <h3>Ruby/Tk</h3>

                <p>Ruby/Tk provides Ruby with a graphical user interface (GUI). The Tk extension works on Windows, Mac OS X and Unix systems.</p>

                <p>Previous versions of the Ruby One-Click Installer contained an (old) version of Tcl/Tk. Now this Ruby installer only contains the Ruby bindings to whatever version of Tcl/Tk you wish to install. It's recommended to use <a href="http://www.activestate.com/store/freedownload.aspx?prdGuid=f0cd6399-fefb-466e-ba17-220dcd6f4078">ActiveTcl</a>. Download the file ActiveTcl8.4.13.0.261555-win32-ix86-threaded.exe and install it. Reboot your PC.</p>

                <p class="post-note">
                Tk works along a composition model - that is, you start by creating a container (such as a <strong>TkFrame</strong> or <strong>TkRoot</strong>) and then create widgets (GUI components) that populate it, such as buttons or labels. When you are ready to start the GUI, you invoke <strong>Tk.mainloop</strong>. The Tk engine then takes control of the program, displaying widgets and calling your code in response to GUI events.
                </p>

                <h3>Simple Tk applications</h3>

                <p>Let's understand the following program <strong>p074hellotk.rb</strong></p>

                <div class="column2">
                <!-- InstanceBeginEditable name="Code" -->
                <textarea name="code" class="ruby:nogutter:nocontrols" rows="15" cols="60">
                require 'tk'
                hello = TkRoot.new {title "Hello World"}
                Tk.mainloop
                </textarea>
                <!-- InstanceEndEditable -->
                </div>

                <p>The <a href="http://www.jbrowse.com/text/rubytk_en.html" >Tk documentation</a> shows the class hierarchy. Briefly, the hierarchy is as follows:</p>

                <p><small>Object->TclTkIp->TkKernel->TkObject->TkWindow->TkRoot<br />Object->TclTkIp->TkKernel->TkObject->TkWindow->TkLabel->TkButton</small></p>

                <p>There are many modules like:<br /><strong>Tk, Tk::Wm</strong> and many others.</p>

                <p><strong>TkKernel</strong> is the superclass of <strong>TkObject</strong>. The subclass redefines the class method <strong>new</strong> to take a block.<br /><strong>TkObject</strong> is the superclass of all widgets and has an included Tk module.<br /><strong>TkRoot</strong> class represents the root widget. The root widget is at the top of the Ruby/Tk widget hierarchy and has the included module <strong>Tk::Wm</strong> for communicating with a window manager. The methods introduced here are normally used as instance methods of <strong>TkRoot</strong>.</p>

                <p>In the program, after loading the tk extension module, we create a root-level frame using <strong>TkRoot.new</strong>. With Tk you create widgets and then bind code blocks to them. When something happens (like the user clicking a widget), Tk runs the appropriate code block. In our program, we use the <strong>title</strong> and <strong>minsize</strong> instance methods (of module <strong>Tk::Wm</strong>) in the code block to <strong>TkRoot.new</strong>. We are now ready with our GUI and we invoke <strong>Tk.mainloop</strong></p>

                <p>Let us now add some widgets to the above program, namely a <strong>TkLabel</strong>. The modified program is <strong>p075hellotk1.rb</strong></p>

                <div class="column2">
                <!-- InstanceBeginEditable name="Code" -->
                <textarea name="code" class="ruby:nogutter:nocontrols" rows="15" cols="60">
                require 'tk'
                hello = TkRoot.new do
                  title "Hello World"
                  # the min size of window
                  minsize(400,400)
                end
                TkLabel.new(hello) do
                  text 'Hello World'
                  foreground 'red'
                  pack { padx 15; pady 15; side 'left'}
                end
                Tk.mainloop
                </textarea>
                <!-- InstanceEndEditable -->
                </div>

                <p>Here, we make a <strong>TkLabel</strong> widget (representing a label) as a child of the root frame, setting several options for the label. Finally, we pack the root frame and enter the main GUI event loop.</p>

                <p>We also need to be able to get information back from our widgets while our program is running by setting up callbacks (routines invoked when certain events happen) and sharing data. The next example, <strong>p076hellotk2.rb</strong> does that.</p>

                <div class="column2">
                <!-- InstanceBeginEditable name="Code" -->
                <textarea name="code" class="ruby:nogutter:nocontrols" rows="15" cols="60">
                require 'tk'
                TkButton.new do
                  text "EXIT"
                  command { exit }
                  pack('side'=>'left', 'padx'=>10, 'pady'=>10)
                end
                Tk.mainloop
                </textarea>
                <!-- InstanceEndEditable -->
                </div>

                <p>Callbacks are very easy to setup. The <strong>command</strong> option takes a <strong>Proc</strong> object, which will be called when the callback fires. This means that the code block passed into the command method is run when the user clicks the button, allowing you to programmatically execute the same functionality that would be invoked on an actual button press. Note that the <strong>Kernel#exit</strong> method terminates your program here.</p>

                <p>We shall now build a rudimentary GUI interface to our SOAP server hosted at www.puneruby.com. The program is the <strong>p077soapguiclient.rb</strong></p>

                <div class="column2">
                <!-- InstanceBeginEditable name="Code" -->
                <textarea name="code" class="ruby:nogutter:nocontrols" rows="15" cols="60">
                require 'soap/rpc/driver'
                require 'tk'

                class SOAPGuiClient
                  def connect
                    @buttonconnect.configure('text' => 'Reset')
                    @buttonconnect.command { reset }

                    begin
                      driver = SOAP::RPC::Driver.new('http://217.160.200.122:12321/',
                                                     'urn:mySoapServer')
                      driver.add_method('sayhelloto', 'username')
                      s = driver.sayhelloto('Satish Talim')
                    rescue Exception => e
                      s = "Exception occured: " + e
                    ensure
                      @label.configure('text' => s)
                    end
                  end #connect

                  def reset
                    @label.configure('text' => "")
                    @buttonconnect.configure('text' => 'Connect')
                    @buttonconnect.command { connect }
                  end # reset

                #---
                  def initialize
                    root = TkRoot.new do
                      title 'SOAP Client'
                      # the min size of window
                      minsize(535, 100)
                    end
                #---
                    @label = TkLabel.new(root) do
                      pack
                    end
                #---
                    @buttonconnect = TkButton.new(root)
                    @buttonconnect.configure('text' => 'Connect')
                    @buttonconnect.command { connect }
                    @buttonconnect.pack('side'=>'bottom')
                #---
                    Tk.mainloop
                  end #initialize
                end # class

                SOAPGuiClient.new
                #---
                </textarea>
                <!-- InstanceEndEditable -->
                </div>

                <h3>Logger class</h3>

                <p>In the above program, we reconfigure a widget while it's running. Every widget supports the <strong>configure</strong> method, which takes a code block in the same manner as <strong>new</strong>. We have also modified the earlier <strong>p072soapserver.rb</strong> program, as below. We have included the <strong>Logger</strong> class.</p>

                <div class="column2">
                <!-- InstanceBeginEditable name="Code" -->
                <textarea name="code" class="ruby:nogutter:nocontrols" rows="15" cols="60">
                require 'logger'
                require 'soap/rpc/standaloneServer'

                class MyServer &lt; SOAP::RPC::StandaloneServer
                  def initialize(* args)
                    super
                    add_method(self, 'sayhelloto', 'username')
                    @log = Logger.new("soapserver.log", 5, 10*1024)
                  end

                  def sayhelloto(username)
                    t = Time.now
                    @log.info("#{username} logged on #{t}")
                    "Hello, #{username} on #{t}."
                  end
                end

                server = MyServer.new('PuneRubyServer','urn:mySoapServer','www.puneruby.com',12321)
                trap('INT') {server.shutdown}
                server.start
                </textarea>
                <!-- InstanceEndEditable -->
                </div>

                <p>The <strong>Logger</strong> class helps write log messages to a file or stream. It supports time- or size-based rolling of log files. Messages can be assigned severities, and only those messages at or above the logger's current reporting level will be logged. Here, we log to a file called soapserver.log, which is rotated when it gets about 10K bytes and keeps up to five old files.</p>

                <p class="post-footer align-right">
                  <strong>
                    <a href="/satishtalim/ruby_activerecord_and_mysql.html">&lt;ActiveRecord and MySQL | </a>
                    <a href="/satishtalim/tutorial.html">TOC | </a>
                    <a href="http://sitekreator.com/satishtalim/unit_testing.html">Unit Testing&gt;</a>
                  </strong>
                </p>

            </div>
            <!-- main inner ends here -->
        </div>

            <div id="rightbar">

            </div>

    <!-- content-wrap ends here -->
    </div>

<!-- wrap ends here -->
</div>

<!-- footer starts here -->
<div id="footer">
    <!-- CHANGE THE FOOTER -->
    <p>&copy; 2006-2021 <strong>rubylearning.github.io - A Ruby Tutorial</strong>&nbsp;&nbsp;Page Updated: 5th Jan. 2021 | Design: <a href="mailto:ealigam@gmail.com">Erwin Aligam</a> | Valid: <a href="http://validator.w3.org/check/referer">XHTML</a> | <a href="http://jigsaw.w3.org/css-validator/check/referer">CSS</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="/">Home</a> | <a href="/privacy.html">Privacy</a> | <a href="/sitemap.html">Sitemap</a></p>

</div>

<!-- footer ends here -->

<!-- SyntaxHighlighter code -->
<script src="/js/shCore.js" type="text/javascript"></script>
<script src="/js/shBrushRuby.js" type="text/javascript"></script>
<script type="text/javascript">
dp.SyntaxHighlighter.HighlightAll('code');
</script>
<!-- SyntaxHighlighter code -->

</body>
</html>
